/************************************************************************
 * 
 *  handle histogramming
 * 
 ************************************************************************/

#include "HistoManager.hh"

using namespace std;

ClassImp(Barrel)
ClassImp(Annular)

HistoManager::HistoManager(MiniBallRootGenerator* histGen, Data* Data)
  :MiniBallHistoManager(histGen), data(Data)
{ 
  //new stuff
  histGen->Open();
  fFBarrelBranch = new vector<Barrel>;
  fBBarrelBranch = new vector<Barrel>;
  fFCDBranch = new vector<Annular>;
  fBCDBranch = new vector<Annular>;
  fMiniball = new vector<Germanium>;

  int BufferSize = 1024000;
  if(gROOT->GetFile() == NULL){
    cerr<<"Error, no root file is open!"<<endl;
    exit(2);
  }

  //cout<<"opening tree in file "<<gROOT->GetFile()->GetName()<<", pwd = ";
  //gROOT->GetFile()->pwd();
  //cout<<endl;
  fdatatree = new TTree("caltr","calibrated events");
  //cout<<"created tree "<<fdatatree->GetName()<<"/"<<fdatatree->GetTitle()<<", current file = "<<fdatatree->GetCurrentFile()->GetName()<<endl;
  
  fdatatree->Branch("ForwardBarrel",&fFBarrelBranch, BufferSize);
  fdatatree->Branch("BackwardBarrel",&fBBarrelBranch, BufferSize);
  fdatatree->Branch("ForwardCD",&fFCDBranch, BufferSize);
  fdatatree->Branch("BackwardCD",&fBCDBranch, BufferSize);
  fdatatree->Branch("Miniball",&fMiniball, BufferSize);
  fdatatree->Branch("EbisTime",&fEbisTime,"EbisTime/L", BufferSize);
  fdatatree->Branch("T1Time",&fT1Time,"T1Time/L", BufferSize);
  fdatatree->Branch("SuperCycleTime",&fSuperCycleTime,"SuperCycleTime/L", BufferSize);
  fdatatree->BranchRef();

  Long64_t GByte = 1073741824L;
  fdatatree->SetMaxTreeSize(2*GByte);

  fsimtree = new TTree("simtr","additional information for simulation");
  fsimtree->Branch("EventNumber",&(data->EventNumber),"EventNumber/I");
  fsimtree->Branch("Reaction", &(data->Reaction),"Reaction/I"); 
  fsimtree->Branch("ReactionX", &(data->ReactionX),"ReactionX/D"); 
  fsimtree->Branch("ReactionY", &(data->ReactionY),"ReactionY/D"); 
  fsimtree->Branch("ReactionZ", &(data->ReactionZ),"ReactionZ/D");
  fsimtree->Branch("TargetZ", &(data->TargetZ),"TargetZ/D");
  fsimtree->Branch("ReactionEnergy", &(data->ReactionEnergy),"ReactionEnergy/D");
  fsimtree->Branch("ThetaCm", &(data->Theta_cm),"ThetaCm/D");
  fsimtree->Branch("EexEnergy", &(data->EexEnergy),"EexEnergy/D");
  fsimtree->Branch("EjectileEnergy", &(data->EjectileEnergy),"EjectileEnergy/D");
  fsimtree->Branch("EjectileTheta", &(data->EjectileTheta),"EjectileTheta/D");
  fsimtree->Branch("EjectilePhi", &(data->EjectilePhi),"EjectilePhi/D");
  fsimtree->Branch("RecoilEnergy", &(data->RecoilEnergy),"RecoilEnergy/D");
  fsimtree->Branch("RecoilTheta", &(data->RecoilTheta),"RecoilTheta/D");
  fsimtree->Branch("RecoilPhi", &(data->RecoilPhi),"RecoilPhi/D");
  fsimtree->Branch("Transfer", &(data->Transfer),"Transfer/D");

  cl = new TTree("cl", data->CommandLine);

  //cl->Branch("settings","Settings",&(data->settings));
  data->CreateBranches(cl);
  cl->Write();

}

HistoManager::~HistoManager(){
  Close();
  delete fdatatree;
  delete fsimtree;
  delete cl;

  delete fFBarrelBranch;
  delete fBBarrelBranch;
  delete fFCDBranch;
  delete fBCDBranch;
  delete fMiniball;
}
void HistoManager::EndOfEvent(){
  if(data->VerboseLevel > 5){
    cout<<__PRETTY_FUNCTION__<<endl;
  }
  
  if(WriteGaussian){
    if(data->VerboseLevel > 3){
      cout<<"Adding Gaussian!"<<endl;
    }
    AddGaussian();
  }
  if(ElectronicThreshold){
    if(data->VerboseLevel > 3){
      cout<<"Setting Cutoff!"<<endl;
    }
    SetCutoff();
  }
  
  FillMiniballBranch();
  
  if(DataWritten){
    FillTree();
  }
  
  Clear();
}
void HistoManager::FillFBBranch(Barrel* FBarrel){
  fFBarrelBranch->push_back(*FBarrel);
  DataWritten = true;

  data->HitsInFBarrel++;
}
void HistoManager::FillBBBranch(Barrel* BBarrel){
  fBBarrelBranch->push_back(*BBarrel);
  DataWritten = true;

  data->HitsInBBarrel++;
}
void HistoManager::FillFCDBranch(Annular* FCD){
  //cout << "filling FCDBranch" << endl;
  fFCDBranch->push_back(*FCD);
  DataWritten = true;

  data->HitsInFCD++;
}
void HistoManager::FillBCDBranch(Annular* BCD){
  //cout << "filling BCDBranch" << endl;
  fBCDBranch->push_back(*BCD);
  DataWritten = true;

  data->HitsInBCD++;
}

void HistoManager::FillMiniballBranch(){

  for(int c=0;c<(int)cryostats.size();c++){
    Germanium Cluster;
    Cluster.SetCluID(c);
    bool hit = false;
    for(int cry=0; cry < (int) (cryostats[c]->detectorIDs.size()); cry++){
      int det = (int) cryostats[c]->detectorIDs[cry];
      if(detectors[det]->CoreEnAccu > 0){
	Cluster.SetCore(cry, detectors[det]->CoreEnAccu/EnergyUnit, data->EventTime); 
	for(int seg=0; seg<NB_OF_SEGMENTS; seg++){
	  if(detectors[det]->SegmentEnAccu[seg] > 0){
	    Cluster.SetSegment(cry, seg, detectors[det]->SegmentEnAccu[seg]/EnergyUnit, data->EventTime); 
	  }
	}
	hit = true;
      }
    }
    if(hit){
      fMiniball->push_back(Cluster);	
      DataWritten = true;
      data->HitsInMiniball++;
    }

  }

}

void HistoManager::FillTree()
{
  fdatatree->Fill();
  fsimtree->Fill();
  
  if(data->VerboseLevel > 5)
    {
      cout<<"forward barrel: "<<fFBarrelBranch->size()<<", backward barrel: "<<fBBarrelBranch->size()<<", forward cd: "<<fFCDBranch->size()<<", backward cd: "<<fBCDBranch->size()<<" detectors"<<endl;
      cout<<"filled datatree and simtree: "<<fdatatree->GetEntries()<<" and "<<fsimtree->GetEntries()<<" entries"<<endl;
    }
  
  data->DetectedEventNumber++;
}
void HistoManager::Clear(){
  if(fFBarrelBranch != NULL){
    fFBarrelBranch->clear();
  }
  if(fBBarrelBranch != NULL){
    fBBarrelBranch->clear();
  }
  if(fFCDBranch != NULL){
    fFCDBranch->clear();
  }
  if(fBCDBranch != NULL){
    fBCDBranch->clear();
  }
  if(fMiniball != NULL){
    fMiniball->clear();
  }
  fEbisTime = 0;
  fT1Time = 0;
  fSuperCycleTime = 0;  
  // resets all entries for accumulation of energy during an event
  InitMBAccumulation();
  //resets all entries 
  InitMBInteraction();
}
void HistoManager::Close(){
  cout << "writing trees" << endl; 
  
  fdatatree->Write();
  fsimtree->Write();
}

double HistoManager::GetEnergyUnit(){
  return EnergyUnit;
}
void HistoManager::Status(){
  if(WriteGaussian){
    cout<<"Adding Gaussian!"<<endl;
  }
  if(ElectronicThreshold){
    cout<<"Setting Cutoff!"<<endl;
  }
  
  return;
}
